{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Variational GPs w/ Multiple Outputs\n",
    "\n",
    "## Introduction\n",
    "\n",
    "In this example, we will demonstrate how to construct approximate/variational GPs that can model vector-valued functions (e.g. multitask/multi-output GPs).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "import torch\n",
    "import gpytorch\n",
    "import tqdm\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "%matplotlib inline\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set up training data\n",
    "\n",
    "In the next cell, we set up the training data for this example. We'll be using 100 regularly spaced points on [0,1] which we evaluate the function on and add Gaussian noise to get the training labels.\n",
    "\n",
    "We'll have two functions - a sine function (y1) and a cosine function (y2).\n",
    "\n",
    "For MTGPs, our `train_targets` will actually have two dimensions: with the second dimension corresponding to the different tasks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_x = torch.linspace(0, 1, 100)\n",
    "\n",
    "train_y = torch.stack([\n",
    "    torch.sin(train_x * (2 * math.pi)) + torch.randn(train_x.size()) * 0.2,\n",
    "    torch.cos(train_x * (2 * math.pi)) + torch.randn(train_x.size()) * 0.2,\n",
    "], -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define a multitask model\n",
    "\n",
    "This model should look like a combination of the [SVGP regression example](./SVGP_Regression_CUDA.ipynb) and the [batch independent multitask GP example](../03_Multitask_Exact_GPs/Batch_Independent_Multioutput_GP.ipynb).\n",
    "\n",
    "We are going to construct a batch variational GP - using a `CholeskyVariationalDistribution` and a `VariationalStrategy`. Each of the batch dimensions is going to correspond to one of the outputs. In addition, we will wrap the variational strategy to make the output appear as a `MultitaskMultivariateNormal` distribution. Here are the changes that we'll need to make:\n",
    "\n",
    "1. Our inducing points will need to have shape `2 x m x 1` (where `m` is the number of inducing points). This ensures that we learn a different set of inducing points for each output dimension.\n",
    "1. The `CholeskyVariationalDistribution`, mean module, and covariance modules will all need to include a `batch_shape=torch.Size([2])` argument. This ensures that we learn a different set of variational parameters and hyperparameters for each output dimension.\n",
    "1. The `VariationalStrategy` object should be wrapped in a `~gpytorch.variational.MultitaskVariationalStrategy`. This converts the output from a batch MultivariateNormal distribution into a MultitaskMultivariateNormal distribution. This makes it possible to use multitask likelihooods (e.g. `~gpytorch.likelihoods.MultitaskGaussianLikelihood`, `~gpytorch.likelihoods.SoftmaxLikelihood`, etc.) with this model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MultitaskGPModel(gpytorch.models.ApproximateGP):\n",
    "    def __init__(self, inducing_points):\n",
    "        # We have to mark the CholeskyVariationalDistribution as batch\n",
    "        # so that we learn a variational distribution for each task\n",
    "        variational_distribution = gpytorch.variational.CholeskyVariationalDistribution(\n",
    "            inducing_points.size(-2), batch_shape=torch.Size([2])\n",
    "        )\n",
    "        \n",
    "        # We have to wrap the VariationalStrategy in a MultitaskVariationalStrategy\n",
    "        # so that the output will be a MultitaskMultivariateNormal rather than a batch output\n",
    "        variational_strategy = gpytorch.variational.MultitaskVariationalStrategy(\n",
    "            gpytorch.variational.VariationalStrategy(\n",
    "                self, inducing_points, variational_distribution, learn_inducing_locations=True\n",
    "            ), num_tasks=2\n",
    "        )\n",
    "        \n",
    "        super().__init__(variational_strategy)\n",
    "        \n",
    "        # The mean and covariance modules should be marked as batch\n",
    "        # so we learn a different set of hyperparameters\n",
    "        self.mean_module = gpytorch.means.ConstantMean(batch_shape=torch.Size([2]))\n",
    "        self.covar_module = gpytorch.kernels.ScaleKernel(\n",
    "            gpytorch.kernels.RBFKernel(batch_shape=torch.Size([2])),\n",
    "            batch_shape=torch.Size([2])\n",
    "        )\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # The forward function should be written as if we were dealing with each output\n",
    "        # dimension in batch\n",
    "        mean_x = self.mean_module(x)\n",
    "        covar_x = self.covar_module(x)\n",
    "        return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)\n",
    "\n",
    "\n",
    "# The shape of the inducing points should be (2 x m x 1) - so that we learn different inducing\n",
    "# points for each output\n",
    "inducing_points = torch.rand(2, 16, 1)\n",
    "model = MultitaskGPModel(inducing_points)\n",
    "\n",
    "# We're going to use a multitask likeihood with this model\n",
    "likelihood = gpytorch.likelihoods.MultitaskGaussianLikelihood(num_tasks=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With all of the `batch_shape` arguments - it may look like we're learning a batch of GPs. However, the `MultitaskVariationalStrategy` object converts this into a (non-batch) MultitaskMultivariateNormal, where each of the tasks represents an output."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MultitaskMultivariateNormal(loc: torch.Size([200]))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model(train_x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([100, 2])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model(train_x).rsample().shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Train the model\n",
    "\n",
    "This code should look similar to the SVGP training code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "149441d143674f9eb3e4ca46169b208f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=20, style=ProgressStyle(description_width='initia…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Minibatch', style=ProgressStyle(description_width='initial'))…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# this is for running the notebook in our testing framework\n",
    "import os\n",
    "smoke_test = ('CI' in os.environ)\n",
    "num_epochs = 1 if smoke_test else 20\n",
    "\n",
    "\n",
    "model.train()\n",
    "likelihood.train()\n",
    "\n",
    "# We use SGD here, rather than Adam. Emperically, we find that SGD is better for variational regression\n",
    "optimizer = torch.optim.Adam([\n",
    "    {'params': model.parameters()},\n",
    "    {'params': likelihood.parameters()},\n",
    "], lr=0.01)\n",
    "\n",
    "# Training loader\n",
    "train_loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(train_x, train_y))\n",
    "\n",
    "# Our loss object. We're using the VariationalELBO, which essentially just computes the ELBO\n",
    "mll = gpytorch.mlls.VariationalELBO(likelihood, model, num_data=train_y.size(0))\n",
    "\n",
    "# We use more CG iterations here because the preconditioner introduced in the NeurIPS paper seems to be less\n",
    "# effective for VI.\n",
    "epochs_iter = tqdm.notebook.tqdm(range(num_epochs), desc=\"Epoch\")\n",
    "for i in epochs_iter:\n",
    "    # Within each iteration, we will go over each minibatch of data\n",
    "    minibatch_iter = tqdm.notebook.tqdm(train_loader, desc=\"Minibatch\", leave=False)\n",
    "    for x_batch, y_batch in minibatch_iter:\n",
    "        optimizer.zero_grad()\n",
    "        output = model(x_batch)\n",
    "        loss = -mll(output, y_batch)\n",
    "        minibatch_iter.set_postfix(loss=loss.item())\n",
    "        loss.backward()\n",
    "        optimizer.step()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Make predictions with the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAADPCAYAAACwVAtKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOydd5hTZfb4P2+SmWR6r1TpSJcgoggoKFIUZUUULKsu7K5iW9EFRf3ZkF3dr2KBFWRFRKooUqVJlQEc6tAZGGaYXjM9/f7+yCRkeqYwk4H7eR4eJsktJzf33PO+55z3HCFJEjIyMjIyMjLXHkVzCyAjIyMjI3OjIBtdGRkZGRmZJkI2ujIyMjIyMk2EbHRlZGRkZGSaCNnoysjIyMjINBGy0ZWRkZGRkWkiZKMrIyMjIyPTRMhGtxaEEGOFEKub+Jz9hRC7GniMmUKIfzaSSAghvIUQETV8/pAQYpoQop8QYmdd5BNC/J8Qoo8QYooQ4rMGyukphPhCCDFJCHFTQ44lc30h67LjeLIuNyOy0S1DCNFDCPGeEOIvQohZQohxZR9tBcKaUhZJkg4DmgryDRFCFAghnnN6b7IQ4kchhF8VhzkCeDSGPEIIL+ARoEgI8bEQIk4I0auCzD8D8yRJOurieZ3le02SpOPAfsC3IbJKkmQEzmG7t7OFENMacjyZloesy9Uj63Lzo2puAdwBIUQrYDWglSSppOy99UIInSRJu4UQzSGW3vmFJEl7hBD/Azyd3jYDr0iSVFjF/pZGlGUW8B9JkoqFEFuAKEmS4ipuJEmS1Umu2nDIJ0mS/W9DgyW1oS87bqEQ4ooQYqwkSRsa6dgyboysy7Ui63IzI890bTwN7LcraRlrgOllf3sLIT4VQsQLIQaVuT1mCiFeFEJ8ACCEeFwI8WchxFohRFjZ9p8KIU4KIZ4UQiQKIYKEENFCiIXCxhQhxF+FEKuFEGohRCchxOtCiH8AoVXIOQ/4q7j65GgtSdIVIYRSCLFICPGEEOJL5x2EEL2FECfK/v6zEOKbsr/Hl23/kxCioxBiaNnna4QQnZz29wQGSpKUW93FK7sec4UQkyq8v0QI8agQQlF2Lvv1CXbaJlwIsVMI0brsrWAhxNtCiCOizAUmhPinEOKpsusWUsN7rwghHgMmOomxG/h7dbLLXHfIuizrslsjz3RttAKyKryXBtjjCArgH8Au4H3gGWAA8DjQWQjRG7gdWAccA7oDJ4FAoI8kSRYhxFRADXQBPgTGlp33AHAZ6AB8AjxSNgp9tKKQkiSdF0IkASOEEAnA+bKPvIE4YBXwcoV9Tggh7Eq2DxhcpgB/Ar4vO38v4JayYzxHeToCxmqum/0cRiHEGZwGcUKIycC/JEk6JYToBwwENgDHy66Pfd9MIUSG0+HMkiS9J4QIKpO1FFBJkvSdEMIKvCWE2FrFe2uAYEmSPhVChDkdX1d2fpkbA1mXZV12a+SZro2LQFSF90LK3gcokmydIXYDEZIkJQGHgVPYlK07kCZJ0q+SJP0/bAphAXKc3C2LgSeBdpIkXQZuBi6W7fMatthFX0mSisu2dx6pO/MVMA0YDWwCm+sFyAEewDW3Tqey7/SrJEn/xvaAmQ/8DVhKeZdSKFCVy6sizvt4YptZ6Mpe3wyklJ3vHSCmhn0Lyv4vxhYL6+d0/uNAj2reuwOwK3zFayd39bhxkHVZ1mW3Rja6NpYAtwshfJzeewj4uMJ2rYEYIUQHbO6hUdhGy/HA00KI0LKRZ/8qzrECeIyrN2888LwQwksI0Q3b6LhICHFz2efKamTdgO3GVNofAmWj8/GSJK2m6viP3aMRgu03TwAeEkK0F0L4AkOAVpIkDQf+ACY77ZsBBFMNQgiNEGJAhbeNwKvAYiGEouy7PiOECBZCRGFTNFcQ2B6G2rLXPtiSNqp6LxXbDMWO871d6uL5ZFo+si7LuuzWyEYXm1sEmAC8LcoyHoElkiTtK9vksrBlzo0HZgL+wDJsbpZFZRmKa7C5dN7EduNogSFCCE3ZOYqAbdgyKAF+xnYDn8emZPHAS8ASIcQrgK8QomcVslqB/5btbycD6CNsMaliYcvW1AK9hRDewG9CiA3YbuQobIr0L+AgtlHx78DjQogZ2Eaqm53Od56y0WXZg2wYcJsQ4jUhxEzg17Lv0BfoL4Togc3tloDt/vocOIPtAXMKeL3setnla4XN7TUAuA3oKIRoD3TF5iZbDxQKIV4FhgNzsI3mK763ouya/a/sd+kphFCVPTj3VryOMtcnsi7LuuzuCLmfrkxtCCGeB7ZKknShuWWpK2XJGGfLlj/IyNzQyLrc/MgzXRlXmAcMsI/0WwpCiFAgr6UrqYxMIyLrcjNTr5muVqsNAj7F5lZ4PzY2dmVjCybjfggh/CVJKqh9S/egpcnbXMj6fOPR0nSjpclbE/Wd6YZjS7W/l/LrqGSuY1raTd/S5G1GZH2+wWhputHS5K2JBsV0tVrtQMArNjZ2V6NJJCMj0yzI+iwjc+2pd3EMrVbbAVumWRa2heZVMmPGDDlTS0bGRebMmdMsdQpd0WdZl2VkXKc6Xa630Y2Njb2k1WqHAye0Wm1YbGxsxSowDt59990aj5WZmUl4eHh9RbkmyDK5hiyTa7gi0zvvvNNE0lTGVX2uTZeh5V7/psTd5AFZJldpqC43KHs5NjbWiq30WLW1PGVkZFoGsj7LyFx76jXT1Wq1L2MrB/Y78HVsbGxjdsGQkZFpQmR9lpFpOupldGNjYxvUnFjm+sFgMHDx4kXcqciK1WqloMC9kh2dZRJCoFariYyMRKVq/p4jsj7LgO0eTU5OxmAwuI0+u7sug02fw8LC8Pf3d2n/5td4mRaNwWCgdevWaDTus9beZDLh4dEoPb8bDWeZJElCp9ORnp5O69ata9lTRqZpKC4uJjg4mFatWiGap+9wJdxdlwH0ej0ZGRkuG125IpVMg7BarajV6uYWo0UhhCAwMBCDobH6fMvINByLxUJgYKDbGNyWglqtxmw2175hGbLRlWkwrihpWloaI0aMID09vQkkcn+EEG7jwpORseOqwZX1+Sp11WXZ6Mo0CR999BH79+9n9uzZ9T7GwoULWbt2LcuWLWPFihUAvPfee+zZs6exxCxHXl4ejzzyiON1UVERkyZNYsaMGSxdupS//e1vHDly5JqcW0bGnZH1uf7IMV2Za0pgYCB6vd7xesGCBSxYsACNRoNOp6thz/KsXGkrB/zggw8CMGvWLH7//Xfat29/zWaMQUFB5eI0vr6+dO/enSFDhjB06FBGjRrFyJEjOXDgQLmEqJycHDZv3szjjz9+TeSSkWkuZH1uOLLRlbmmnDlzhhkzZrBu3TpKS0vx8vJi3LhxzJkzp07HWb9+Pf/85z8drwcMGMCGDRvo3r0727Zt49NPP2XChAlERESQm5tLbGwss2fPZuHCheh0Orp27UpcXBySJOHt7c0vv/zCkiVLyM7OJj09HavVisViYdeuXXz55Zd8/vnndOjQgYsXL1YrU0hICG3btiUuLo6ffvqJm2++mfz8fDp27MjWrVsZMmQIX331FW3btiUqKorx48fX+zrKyLgDTa3PoaGhFBUVcfDgQbfR51atWtG+fXseeOCBel1D2b0sc02JiorC398fg8GARqPBYDDg7+9PZGRknY5jtVrLjYA9PDxQKpUA3HPPPSxfvpyFCxdSWFjI1q1befbZZ9m+fTuFhYX069ePlJQUbrrpJu68805ef/11Xn75ZWJiYsjKymLcuHGsXr2asLAwgoKC2Lt3Lx4eHowdO5YOHTrUKptGo+HBBx8kPDycw4cP07lzZzp37kzbtm0ZN24cgYGBnDx5sm4XTkbGDWkOfd6yZYvb6fOJEyfqduGckI2uzDUnMzOTKVOmsGfPHqZMmUJGRkadjzF69Gh+//13x+sjR45w//33O15rNBqio6MZNGgQkydPZsqUKZhMJoQQ3HfffYwdOxbA4TYaN24cv/zyi0PRMzIyGDx4MM899xzp6enk5tqKMtWUWJKXl0dubi5dunRhyZIlDBs2DEmSHPvk5+ezfv167rjjDjlpSua6oSn1+bbbbuOJJ55wK32+/fbbG6TPsntZ5ppjj98AzJ07t17HmDx5Ml999RVr167FbDbTvXt3Bg4ciMViYfv27cTHx/P666+zcuVKgoODueeeexg5ciQLFizg4MGDvPzyy8THx5Ofn8/QoUPx9PSkd+/eDBw4EIBHHnmEYcOGMXbsWF566SUmTZrEl19+SUZGBsnJybRu3ZqioiJOnTqF0WgkPz+fQ4cOsWjRIhQKBadPn+b7778nKysLhULByZMn0el0xMTE0LFjR86ePYter3er9cwyMvWhKfV51apVREZGupU+t2/fvkH63KDWfq4wY8YMSW540Di4o0znz5+nS5cuzS1GOVrCgnqA+Ph4OnXq5Hj9zjvvNFuXIVdwRZfBPe9Td5PJ3eQBWZddpaG6LLuXZWRkZGRkmgjZ6MrIyMjIyDQRstGVkZGRkZFpImSjKyMjIyMj00TIRldGRkZGRqaJkI2uTItg2bJl9OjRo9z6uBdffJF//OMfGI3GZpRMRkamrtzI+iyv05VpFDSaxmvvp9dXbnl3++23ExYWxpYtW7jvvvsoLCzk8uXLPPzww3h6ejbauWVkbnSutS7Dja3PstGVaTFMnTqVr7/+mvvuu48NGzYwZswYzGYz8+fPd9RjVSqVZGdnc/jwYWbPns3TTz/NhAkT+O6779i4cWO5QuYyMjLNhyv6LEkShYWFHDp06LrRZ9m9LNMo6PWGRvtXHe3atUOlUnHhwgX0ej1eXl6YTKZy9VhvvvlmunbtSlJSEoGBgQQHBzNp0iRatWol9/6UkXGBptBlcE2fu3fvTrdu3a4rfa6X0dVqtX5arXa1Vqu9pNVq5zW2UDIy1TF16lSeffZZhgwZAoDFYilXj3Xjxo0EBQU5CrDb66YqFArMZnOzye3OyPos01zUps+bN28mODj4utLn+s50bwP+DPQEhmu12gGNJpGMTBUcOnSIo0ePMmLECG677TbatGnD8ePHSUhIYPv27Tz88MOkpKRgMBj49ttvKSkpYc+ePVy8eJHExETS0tJqbOt1gyPrs0yTUhd9XrRo0XWlz/VyiMfGxm6z/63Vak8CLXOeL9NieOSRRxx///vf/wbgP//5T6XtBg8eXK426s6dOwHYuHFjE0jZMpH1WaapcVWfBw4cWK7O8fWgzw2KQmu1Wj8gKTY29kpN22VmZtZ4HJ1O1xAxrgmyTK5htVoxmUzNLUY5LBZLc4tQiapkslqttepGU+KKPrsirzvep+4mk7vJA7Iuu0pDdbmhqV9PAG/XtpEr3TTcreMGyDK5gk6nc7suIECLkEmhULjb71mrPrsqr5t9L8D9ZHI3eWRddp2G6HK9s5e1Wu2DwNrY2NhCrVYbUd/jyMjIND+yPsvINA31zV5+DvgUWKfVak8AYxpVKhkZmSZD1mcZmaajvolU84DrfmmB3mQhq8hITpGREqMZg9mKwWzFYpXwVClQqxRoPJT4a1SE+aoJ9vFwpLTLyLQUbhR9lpFxB1peOY9riMFkITG3lMs5JZxLzgKPwjrt76FUEOanpn2IN53DfPD3cr9YxLXki50NT+F/4a6O1X62cOFCgoKC0Gg0rFy5ku+//77GY5lMJn788Uf27t1LSUkJixcvBsBsNvP8888zc+ZM2rdv32CZZWSuN661LsONq883vNE1W6zEZxVzNr2QFJ0ea1kB7mKjBZ862kyTxUqqrpRUXSn7L+YQ6a+ha4Qv3SL98FTJxb8awurVqzGbzTz88MMA+Pn51bpPXFwcRqORefPKT+JUKhWtW7e+JnLKyMjUzo2szzesJdCVmNgbn8O3MUlsO5PJlbxSh8FtLNIL9Oy+kM13B5I4dDkPvcn90t9bCmvWrHFUrQEYOnQoCxYsYPv27bz++uvk5OTw0EMPsWzZMkcN1507d3Ly5ElSU1OZMGECAMuXL2fTpk3s27cPgJ9//pkff/yRadOmcfbsWR577DE++eQTXnjhBQCWLFnCd999x+zZs7l8+TKLFy9m2rRpXLhwoekvgozMdYKr+rxixQpGjhx5XenzDWd0s4sM/Hoqg6UHr3Dsiq5JDKHeZOFgQi6LY5I4kJCLyWK95ue83rBYLOXWECYmJpKQkMCIESMICgri0KFDleqyarVaevXqRXR0NAEBAej1erZt28bo0aO54447ANuIOywsjKCgIFq3bo2Pjw/Tp0/n3LlznDlzBr1ez1NPPcXkyZNZsGABUVFRaLVaEhISmutSuDUJ2cXsvpjPldyScm3bZGSccVWfH3300etOn28Y93J2kYGDCXkkZJcg0TwPA5PFyh+X8ziXXsSdnUPoEOrTLHK0REaOHMn27dvp27cvAFeuXOHKFVsNh9DQUAICAhxJbEKIKuuylpaWkpKS4tgGICMjg8GDB9OlS5dya+8kScJqtXL69GnHa4vFQmBgICNHjpSNbjWYrRIXc0pJP56Gn1pF9yg/ekb746O+YR41Mi5QF32urs5yS9Xn636mW6Q3s/1MJiv+SOFSdnGzGVxnCvQmNsals/5EOkWGllm0u6l55plnyMnJ4eOPP+aHH35ACEH79u1ZunQpQgh69OjhqMuanp7OxYsXOXnyJKdOnSI/P5/4+HjMZjN9+/blzTffJDExkfPnz/PII48wbNgwlixZQlJSEmlpaSQmJpKamkp4eDhFRUVMnjyZS5cuMWXKFF555RWeffbZ677nZ2NQaDBz6HIei2OS2Ho6k4yCmrvOyNw4uKrPdp28nvRZXGsX0IwZM6R33323xm0yMzMbvTqL0WzlcJKOY1fyMVvr7s4tLi7Gx+faz0Q1HkqGdwtzadZ7La5TQzl//jxdunRpbjHK4Vx72V2oSqb4+Hg6derkeP3OO+8wZ84ct11z5oouX8gsYs2hS9XqTqtALwa0D6JNkNe1ELFa3E133E0ekHXZVRqqy9flTPdseiFLD14hNjGvXga3KdGbLGyMS2fX+WzMcqxX5jonRVfK2mOprD6cQmJOSbXbpaWlMWLEiBbbM1VGpjquK6ObVWjgxyMpbDuTSbGxZblt41LyWXU4lYJS9yo4LiNzLUgv0LPuRBprjqaSlq+v9PlHH33E/v37mT17djNIJyNz7bgujK7BZGH3+WxWHk6pUoFbCjnFBlYdTiFV17K+g5ylWnckSZKrlwGpulJ+PJLCxrh0couNBAYGotFoWLBgAVarlQULFqDRaAgMDGxuUW8IZF2uO3XV5RZtdCVJ4nRaAd8fvMKJlPwG3TAFuVnMe+0pCnKzGlHCulNqsvDzsVROpxU0qxyuolAoMBjkBJm6IEkSOp0OtVrd3KK4DZeyi1n2RzLfbvqdCRMewcvLFvP18vLi0Ucf5ezZs80s4fWPUqlEp9PdsIbXKkmYLVYMZgulJgslRjPFBjNFejOFejOFehOFehMVL4/BYEClcj07v8Xm8WcUGNhzIZv0gsaZFW5fNp/Lpw6zfdl8Rkz6O0s+fIUn3/wU/+Awl/YvyM1i6UfTeXzmJy7vUx1WSWLH2Sx0JSZu7xjSoGNda9RqNSkpKW6lqFarFYXCvcaTzjIJIVCr1URGRjazVO6FJEkkGzSklSrQ6w1oNBoMBgP+/v7ytWoCfHx8KC4uJjc31230+VrpsiSBRZKwWCUskoTVKlUyptXh5SFQKZWO10IIwsJcf+a3OKNbYrSw/1IOZ9OKGmX5z8wH+mE2GR2vYzauJGbjSsBmiMdPq7VdsGNbu9F2dZ/aOJyko9Rk5a4uoSgU7umKVKvVtGnTprnFKIc7Zoa6o0zuii43m9tGP8KYCY9zfs/PZGRkNLdINwQKhcLtyik2pt5kFRq4lF3MpewSsosMQP2eqaM7edOxTVS95WgxRtdksXI8uYAjSToM5sarIjVz8VY2LPyYkzE7MBnKz5rtBljl4clH64463nee1X7053urNNoV96kvp9MKMJgt3NtdfmDL3Bg89dZcx9+9H3mVW9oEYLJY8VC6l/dCxv0xmq2cSS8kLqWAvBJj7TtUg/MzH9o1SCa3v4utVlvcdunBK8RcymlUgwvgHxyG2tsHs9GA0sO2QFqhsLkOPNQa+t01hmmfLi8X73We1c5cvJV+w8bgodaU22fm4q2NJuPFrGLWx6WXKx8pL6mQuRGQJInDSTqWHUomOa+0ucWRaSHkl5rYdT6b/+1PZM+F7DoZ3Krye5yf+Q3FbY2u1SpxNr2Q5X8ks+NsVr0qN7maHFWky+W20RN58bPlRLTtiNVqQeXhidloQOPty8HNq7h86jAfPHE3r43qQczGlUiSRMzGlbw/eRjHdm/GbDSg8lQ79mloXLciyXmlbD2nw2i2GV55SYWMO5KVkc63b/+10RMSC/Qm1h5LY/eFbLl2uUy1FBvM7DqfzdKDV4hLya/yXqnNLpSbVD3Qr9Izv0fnmxqUTe927mWzxcqZ9CKOJOko0DdszaqrcVZnd1ZY65vo0GsAfe4ay9evP+mI7wJUjLR7qDX0vH04JYUFBEe04rbREziwaTWFednVnqshCVcZRUZCgoMwGa9mCy9YsMCxrEKn09XpeDIyjc1/5/6HpDPHGjW3wY6ExInkfBJzShjRLZzoQE2jHl+m5WKyWIlN1HE8uWpD60x1dqGq/B6wJUqpPNWYDHo81BruHTmSrz6fW+m4ruI2Rje32MjJ1ALOZRQ1uPNPdclRrsRZH3p+Fks/ms7tAcHM+v63cvFeD7UG/5BwctOuoHSaCU96/d+O/cdPe6vG4zc04WrGt1vYvvj/OLZvG6WlpXh5eTFu3DjmzJlT52PJyDQWgYGB6PVXcyIcCYlC8NbSnVUOMOs7AM0vNfHTsVS07QK5tV2Q2yYZyjQNV3JL+O1cdq2TtNrsQsX8HvukSqFQcuS39Q5Ppq+vX4Oy6d3CvbwzXscPh65wPDm/UVrt1SXOWtHVYDeKu1cvwj84DA+NPyZDRxSqMZgMEykp+CtRN62l79DjRHf4ifjjY/n1Ow3/nrqUM4f0pCbo+Gp6ZddFVW6K10b1YOYD/eq0Rtg/OAzJQ4Ner5eXVMi4DWfOnGHixIloNLb1tR5qDSHRbRFQbRysqjiZq7ogSRJ/XM5jzdFU8uUqbjckpUYL285ksvZ4mkte0drsgnN+j3Oo0FBawm2jJ/LCp8u4bfREcrIaFjpxi5murtQMCmXtG7pIdRevqtG0XfE/eOJuJKsV6AT8lditA4ndagC+BdRYy0LKpUW2f6mXALoCsGMFwGz+9479qOuZNz2BOx8KomOvEiLaGaodRY39y2t1nv3aY9D3T3yCS3t/kZdUyDQ7UVFR+Pv7OwqlmAx6clKTgCpmFDXMOAbc+1CddCG9QM+KP5K5q2sYXSJ8r82Xk3E7ruSWsO1MVp3K/bpiF+zPVudQoXP4cfy0txjdybtBstfb6Gq12iHAO7GxscMbJME1oCA3ixN7t3LL8AcY8tCTVcZZryq+GngApPuBEVSVDh4SZSQ40ohfkBnfQAs+AbYfest3X2HrpxBYtl97oAMQSU5aJGvn2fb38LzM4Afbgmjr+MFNBj1Hd27k6M6NjvO46gZ3vglGPDuDsb3kWa5Mw2gMfc7MzOSRx/+M50392PzNx+SkJyNZreUGmFB5mZ6HWoPZZMRsMjriaHUJCRktVracziAtX8/gTiEoZXfzdYvVKnEgIZcjSfn1qtPgbFT3/LSE43u3MGLS3x2Gt6KBtXteGqPokZ16G93Y2Ng9Wq22aftzucj2ZfMpLcrHU60hukO3SnFWswnGTzvMth+yycu8BfB3+jQbodiJZN1Nz0HBTJw+CY131YH5rv37svDNKRhKizEbDQiFwpZrJXVGqRqOf8gECnP7YjK2Z+cqgC8JCPk7Iybp2Lv2GTKvxBMa3Zb8nMxKs19XuZJXyqZTGYzpGSk/bGTqTWPo8+zZK1m80sy5rEyCIgxkp25GqSrEZDhfaUYRf/xguRnHLXffj9ViqdIT5ConUvLJLDRwX48I/DRu4cSTaUQKSk1sOZ3ZoCqEzkbVU6OhtDC/Rq/K1qULSDh5mc3fLmXsX6aDAJ1OgSUalPV0zjb0znRp8VNmZmaNn5eUlmKg4V2BPnhscLVuq1nL95GVrOHIjjCO7w6hpMC5H+IR4Ed8g2LpOiCAAfc+yMHNKZQWnsIi3U9xcdXn27duGcX5uQC2JUZl51Z5JGA2zSMvYx6gBO4FngQeJD+nF2u+APgOeI/s1C2O49nWCmtQqr0pruKkzokqzpwuLqa4sJC7OgWgaOIi+u6YMS3LVG9q1eeadHnXLi8+fi8UuAl4FXgVS5laH/w1n8RzSsJa6cnL3EdhXmtCWwXx8CvvELvtZ4rycvAJDLYZ4rIkxZp0oTouFhfzTVYed3UKJNr/amNyd7v+7iYPuLdMqQVGdsbrMJjrtlysMC+bHz99k4df+RC/oFCgKjvxBzEb30IoetBr8IvkpGpIic8GgoEfAIjdbvsH8P+Adevi6Nu3fsuGmmQ4WFsZL2+vbFSKhhd/r8pt1eO2e+nQ+yO+e6c9Caeu+uIj2ulBWkp0hziGTRjKgU0JFOZJPPqKrUl3ZPsu1TbirhiTAhyvgyNa8dTbn7Nj+QJOHfgNoVBgNm7GQ72TbgN+xi/obQ5uboPFfDvwK7CPgLAPeOSVCRzZsZ7TB3Yw6qkXqnVlVCdTthHicgUjuoU1efcadyxvKMt0bajpO/TtK5j8dCknE4oxGzzRlygp0inJTffAZAggNR5S432BqcBUslOK+e/0XSgUEbyxZDZr5z1fKZ5W3f1eG/uSjdzZyY8+rQNckr05cDd5wD1lSjWo2ZdchErthaqOZmLLt7YlbPvXfueYzT7/n1389OVhkuPDkKx3ALbSl5IVTuyx72nPDzAD+YCEUuUJCCxmEytW/MC9975br+9zXflgyleXisJk+DOnD77Ksd22pgFqLwt9hxZw60gdAWFJ/DDna8ZOsfnqa1vq40xNSVF2Y+kTEIjFbMuoc6SaBwgeek5gMrzAH1sjsc0GBpOfvZFzsTqUqr21ujtq4mx6IREyQjsAACAASURBVB5KBcO6hNZ5XxmZhtK/v8SMNiWsOZSAxVDC0o+mM3X2J2z7YT4HNu2hyy1PUVLQjpRLAUjWAdiSFsdgtY7hg8chuuMaOvUtJig8v076WBWSJLHnQjbZRUZZH1ooFqvEnkv5pJXWfZFN5WS93cRsnA9MBAYDg5y2zgYOAmeAsyiVl3ht4ddsX/4hsdu+R+XpgdlocHhtAJYtg2XL/lWv+gjXldEFyE33JKLtZrJThwMqjHoIa21AOyKJ0wef5d4n3sc/OIyfvqz/etmasuCqnAUbbcW17UH70qJUBo0x0nfYQX7+0pP0xBHs+SkE+ADIrJREYl/POP6l92od+cel5OOpFG7fnUjm+mb7svkknIzl/cnDHO+dP3J1LblNb4Lo2PsdcjO05GXcTOpFf9bO82fjogh6Dy7gtjF5tO/esNKPp9NsNXdvjWi81REy1x69ycLGkxnEZ5fWydthf1ZO+3Q5u1b/j7j9BiymvwEPYgv1gVAY8Qs8REDYKZSq/SSeXoYkmZ0mT+/gH2xCX5zCoDGPOJKu4o8foKQwH5NB36D6CA3JXu4FdNRqtT1jY2NP1vc4jUVKvIadq0O4cGwJktXmXu2qLaL/8Evs3/AXMq9EkXR2n9PSIBv1bVBQVWo5VD8Lti+w3r5sfrlg/pTZWSx4YzIF2e9SWtwV2IRC+QW9Bu/ggamvAOXXDk985b1aZTucpMNDqWBA+yCXv4/MjU1j6XP/zq0wVtNfWSiUSFYLoa3a88Qb/+GzFyZw8cTfyz71Au4HpmAyjODwjkAO7wikQ69ihj+WTee+xdQ3apKWr2dDjoHHgoIJ8vasfQeZZkVXYmL9iTR09Vh/bRvsHWPDwjRSL32JxdS+7BMjsB5YiWRdT0FuMSWFnmjveZDE05YqlxA5P6cfnT6bNV+8y8HNq1Gr1Q2qj9CQ7OU4oNl7uiWc9OK3laGcjfWzvSFM9L4zh3smFRPZ3sDrY/ohWa1cPlW2QzWlHOuSJQmVU8vtVJwF25cG2alo5Lcvm09m0irCWh+htHg88D5WywtcODqW2U89gMV89fkXu3UNsVvXoFR5MGf9sRrlO5CQi4dSQd82ATVuJyMDjafPv+47zIuvvMq5P3ZjMugdhhZw/J+dcplPn/8TSpUHvYeMKhugliIUa5Csq+g5aCphbT4kZmMQl+J8uBTnQ9uuJdz7RBZd+7ueVOVMgcHM6sOpjOkVQatAt1x0IUPZACkuvc5FkmweRhMwHjhB/PHuZZ9kAPOBr4GrzWH63TWGsX95jZ+/+qDKyVNV2Cda0//6BFs3rqt3s5kW6V6WJDh/xIcdK0JJOGlzPXiorYRGbyIt4e/4+N/B3Bd/ruTmtRMS3bZSKcfGLFNXcS2Ys1vCbuTj9m3jtVE9HPtkXrkA/AuFcg8e6p8pKbgJD/Ux2nb9F8nx75c9wBRIVit9h45ySY598Tl4KAU9ov1r31hGphEIi4isFHoJbdWOkKi2XDiyH6vVUm6gu+2HeY6WmnajfDJmAcQsQKkKZdSfT7LnpxCSznnzzax2dOqbQ2nxX5nw0iR++e9HddJNg9nC2mNpjOgeTle5kIbbcTGrmK2nMzFb697QokPP1zh/9CGgf9k7l2jV6UcCQndy4eguxz0mFAqQJMczv7rJU1XYt+3WyZsx99a/PIVblIF0FUmCUwd8+eLlm/hmVjsSTvrg5WtBKD7AZAgjLeF+IJmYjSsxm4wIIRwlv8B2wYUQWC2WcmW9CvNyqjxfxTJ1rpaoe+qtuYyf9hbRHbrx6PTZdL91aKX4b3Ulyd5c8hEvzb2AT8CvmAxKEk69gckw3fb9y27GwzvWOUpI1ni9kNh5LptzGUUuXV8ZmcaguGzQ+cKnyxg05lEi23UmKDwKSbJWcuMV6XLpP3wcXbV3Vmqp+cZ3P3L3xBze+O4Co5/JQO1lIf5YCCkXlrNgZj4JJy9UWWKyJj21ShLbTmdy9Ir7LY+5kTmZWsDmUxl1Nrgz7r+P10Yd5fzRD7AZ3FTgb0BX2nY9gn+wv62GgrCZul53jKjxmd8UtIiZrtUCcb/7s2NFKGkJNiPlG2hmyPgcBo3Jw6i/kw0LD1QbRxVCgSRZ6XXHCHz8gynMy3aMaqoa3VRXps72w0l1Tr6qKv5bUzLWT8veozh/Fe26LSHx7CTgffyChlGoGwdScZ1c4hIS285kohTQKVwe3ctcex59/d+O5Be7fn33/ktVuvHss4c1X7xbpVEG8NRIbP2+LWZTIPAeMIWSwqeBe4nZ+FdiNvYol5NRW1lVCYl98TkUGyzc0TG4yZfYyZTnYEIuhy7nubSt3fs4+Z+fcOpAF1Sel7CYVUAp8CGIz+iqvQW1ZjjH926hTZdele676ma0DekAVxfc2uhazHB0ZwDblweRk2ZbYxsQYmLYhBxuHZmHp8YWn9V4V23ACvNyXL7gzsxcvJWf53/kiEvZkSTbKKyuyVfVuTAqGuMDm1aVayWYePYJYAWwjMK84cBvKD0ewmxMq1PPXkmS2HI6EyEEHcPqt+5RRqYh1ObGqy4x0U6fIfdxeMc6hHgOSZoH/Bfbso8NBEXs5Jl3PWus6Txr+b5K5zx6RUeJ0cLwbmFyNbdmQJIkdp3P5mRqgcv72BKlsvj8pVAKcqMACAw7gi5rAirPFCwmI8Hh0QCUFuYTHBFd4wSr4rEb0gHOVdzS6JoMgkNbA9n9Ywh5mfZswwQ69NrOlA8Go/KsXHPTlULVrlLVLLSh5RqroqJ8Iyb9rVzms8pTjdorhvHTDrLik56YDLfiH3yWm3rMpDDvXJ3OZZUkfj2VweieEdwUKhteGfeiOl2taEhtA98TwGAQL4P0PnkZd/H1DDMTXvmDs4feqFMpyXMZhejNFkb1iMBD2aKibS0ai1Vi65lM4jNdC31dvQ8mA8cpyA0AMlAoXsRQupX+I4Yy5KGP+eyFCeUmLq5MkKobrClVHrTt1qfRZ75udZeVFin4bVUIs//cmbXzosoM7lngKaALl+KmMnPczVXGMp3jqOOnvVVOietDxbiUxWJxqWtRQ6jK2Bfn5xJ/bBEz/ldIeNsS8jL8uHjiU+57qup2aTVhlSQ2n8ogMaekUeWWkblWVMx9EAolvoEhhLZqS8fev9N32Bt4+5+gSKdi+b97k540FZOhajd1dSTmlPDL8TQMjdBWVKZ2jGYr60+kuWxwAf4xbweBYbuBpUAAQrGenne8Qr+79OiLr9bZn/X9by63dbVTXX5N36GjKrWebAzcYqary/bgt3XhHNgUhKHUlkzRqlMpg8ZcIv7YTE4d2IbJYG60GaYrVIxLfff+S3TT3ulSanlDKNLlghBlBTVsXB15hdP+5gQun/Zm3vT2PPt+Em27ulb82zlesfEkjOohz3hlWgbOzREsJiO97hhRzv1ntcDO1Zls+T6MtEsP4O0fx8RXL3H20Hcu62lavp6fjqXxQO9IfNRu8Vi8Lik1Wlh/Ip2MQtebFqQlqFny4QB0WWqgEIVyOlbLAk7+fnUb5xmt9p4H6zRBqusyz4bSrDPd0lKYOlXFe8/ezO41oRhKlXTqU8xfPkjkpc8TGHifQOPj1agzzLo0jHemsWfSNZ2nutHay/MXM+XDRLrfWkhJoYqFb7Qj8Yxraw6d4xUWq8SmkxlczKrfmkcZ15AkiYtZxXKmbAPYvmw+hXnZhLftUOVqg4LcLP474ykG3HuGmwe+AyRSUtCFFR/fw823zamTnmYXGVhzNJWCehRlkKmdQr2ZNUdTazW4zs/o43tC+OKVm8hOUaP2vkTfYW/z0ucj6T98HAGhEVXOaIucvJSuZirb93n1i5UMGT2e0Igo1Brbs1Wj8WLUuD+xbu9h7uwUilrVsPh/sw7pNBo4e1ZgtQq6D8wkP3s6j73+bK1NhRtCUwXLG0J1mc1+QaF4aiSeeusKyz9uxfE9ASx8sy1/+SCJ9jdXXS6vpuQSaf0xRt4cTmc5q7lRsVglzmcUcSRJR26Jka4RfrRqeD+PG4qK921G4kU+ff5PlWYblctNfgEsprRoHIveakNQxDye/08vVBrXGo/nl5r46WgqD/SJIthHrl7VWOQWG/nleBpFhtq7ydmrSi18o5T0xA4A9B+uY/w0A56aKUD5ClEVJ2Su5vIIBCG+nrQN9mLsqpWE+arx1ajgqft44YUXWLRoERqNBqPRQJuIEO7u2xmAzMyqK665SrMaXSFg7lwzG09eYMfa9zl7aBXblxnLGcP6JkNVpCbj0xgug8ampsFGcUEW+TnP0GPQOk7FhPPNrLY8+34SN/WobHhras5gz2o2WyS6R/k15de7LrFYJc6mFxKbqKNAL8+WGkJN9y1U3enLhg6V52OERi8k/fJk8jKmMf+1GKb+W4GrJXwLDWaH4Q33k0dLDSWjQM+6E7VXmbr6mwYAG0lPvBcwIMTL5KTHoi/5BE9NwyZkQgjaBHnRJdyXtsFe1YYSMjMzmTJlCs8++yyLFi2qd/Wpqmj24MVddwWU6xN7rYxhbUrsblQ12LD3Fd2+bD6Jpw8x8L6X6TdsPkd3BfDNrHZM+TDRMeN1juFWtx4YbC7QHWezKDVZuKVt/fpD3uhYrRJnZGPbqNS0jh0q67O93KStF28p6ZcfB1YCS8lJG8RHTxxBqRrNnPWbajyvs96sPQZje0USHaipcR+Z6knMKWHzqQxMltqLXsxcvJU1c5dy+o/pIHUFMoEHCYlOI/F0YiXvZF0mZCE+arpH+dIl3NelmP3KlVczoOfObdxQYrNnL585c4b+Q+9zKdusYjy2LvHZ2pS4NhRCEODlQZsgL7pH+tG7dQDadkEM6hDM7R1DGNA+iH5tAukZ7U+7EG8CvDwafdH9B48N5rVRPYjZuBJJkjiweTlHdwUjxA8Y9QoWvdWW5Au26+jsRq8txiEh8fvFHH6/2HxVWloq8ZlF/HDoCr+dy5INbiNT031bUZ8lq4WIdh154bPlTvG+bcCtIOKBW/DxP0vqpZpnrs56YzBb+OV4mpztX0/OpheyPi7dJYMLkJ3ajvNH/6/M4MYBtwIxZKdcRpIkYjaudFTic+XZLxDcFOrDg32jmXRra/q1CXSLJLlmlyAqKgq1t69LxrBiPLau8VlX3RG+ahWhnho6tgom1NeTUB9P/DSqOhtRi1Uiv9REsq6U5Dw9KbrSOhfydualeWv57Yevys3Wu/a/g/yc/6DxHsqFo62Z+2IA8ABg6/BgX7Om8vBk/LS3ahwRHknSUWqycHeXMBRysYAaSc4rZf/F3DplYd6oqBQKAr09CPbxwFetwkOpwEMp8FAqMFsk9GYLepOVEqOZzEIjhWWDF1cLavS8YwQrPplJYFi0o/Tq1XjfZczGQfgG7qEgtzvzprfn8ZkpdBtQfrlKTeEn6/pj3CvnPtSJw0k6Yi7mIlG5pkJVnNjrx/KPW2E2KQgI+YPwtrOIP3alXH8alaeaXneMYOxfXqvx2S+EoFukL/3bBrplV6lmN7oARbrKlaOcqU4hKr6urftOdUoc5O1J6yAvogI0RAdo8NOoyMzMJDy8Ya3xlApBsI8nwT6e9G4VgCRJpOUbOJNeSHxmEUYXR4B2/IJCK83Ws5Ivk3nlEmGt7wE+Bsai8tgLDMFsOllnN/qZtEKK9GZG9YhA7SH3IK1IfqmJ3y/myJnfNeDjqaR7pB+tAm06FeBVtwFrqdFCZqGBZF0pFzKLHUa4InZ9/unL9yjKyyY4ItrxWcUBdk7GS3h6fs/J/RH87502/OnFNLrfesHhSq4p/GSVJLacysRotsrNQ2pBkiT2xudwPDnf5X32/RLEuq8jkSTBoDG5PPh3H36eF0j8MclRwlcoFFhMRo7t3lztcp45647ROcKHW9sHuaWxteMWRvfZWf/BqLC5faqshVxBIZQetgsqwNbYoCye42r3HbVKSbsQL9oEedEmyBs/TdNcBiEE0YEaogM13NkppGw5ST45xa5nw9kfJoe2rEGSJDKSLgKQeeUs8DCwEbNpOLAJpcfdmI0X67zM6kpeKauPpHJ/70gCvDzq9iWvU4xmK7GJeRxLzsdidW30fiPSMdSHiX3DCA8Pr/cxvDyVtAvxpl2IN7d3CCajwMD5zCLOphdhMF/1FLmaHDli0t9Y8uEr+PpPBQYgSbP4cW400R1+I/XS1dlSjbkPSPx2LotSkxVtOzn3oSpMFivbzmS6PCCVJNj0v3B2/RgKwF2PJDDqz6UIcfU5l5YYT2mhDt/AEMJb30RuRgrevv6VBkdTp7/N/QNaEerr/olvbmF0a6OqeKwz9pZgh3es4/COdVUmYYX4qLkp1Jt2wd5E+qub3X3qqVLQPcqPbpG+xGcVc+hyHrnFVbcidMY+ureXjIzbv93pehhQqB7Gat4I3I5/0BHadJ3G8b3rGDHp73UyvHklRlYdTmF0T7n/6IXMIvbF57i03OFGp7H1SghBZICGyAANt90UTFxqAceu5FNiNLucHPnBE3cjWa0knj4KrAOSgXmkXnoc0BGz8aWyhiai1vBTzKUcSoxm7uwUIjdKcKLEaGFjXDrpBa6FWywWWDM3ij+2BSGEGUn6C/piPULYXMX251xxcbGjSJGdNV+8W84WdGkVztPD+zTuF7qGuK3RrdjxoapKTRVxVjqBICpQQ4dQbzqE+rjtjE0IQedwXzqF+XAhs5jfL7r2cLcPRCwmo6PPrlAosJp1wGi8/Y+Rl9keo/7/UVLwS73WJetNtv6jd3QMoW+bgHp+w5aLrsTE7gvZJOXKiTTugKdKQf+2gfRp5c/ptEIOJChrznCudlnR10AWsAyYBkTQZ+gPPDD1Fce+NeU+HE/Op9RkYUS3cLlRArY1uBvi0sl3oahIQW4WSz58A433L5yLDQKKkaQ/AVuI2YhLK1eKdLkMGjORp59+hoO//khWZkbjfZkmwG2NbsVA+VNvzaUgN6vSyNY/JLxcQ/qQoEDuv607HUN93CJTzVWEEHSJ8KV9iDcxCbnEJRfUmoRgd8FkJidw8cQhR79dyKekYCCwj+KCzsA6YjaOrNdSLKsksTc+m/QCPXd3DcNT1ewJ79cci1XiSJKOPxLzZFeyG6JSKujdOoDO4b6s0BcwaPREBlYxO604Ey7PT8C92Ga+E7h8qgsab09wMfHnfEYRpSYro3tE3BA6UR2JOSVsOZ1Zzu1fE1uWfEvi6feAUNReRoTiT5hNuzAbqTX/xD4Re+H9z/nTHT2I8FfzxJghjfhtmga3s0o1dXyYs/5YpZGt1WLh7gcn8fQzz7Lzl+VkZ2XSu1XLnZV5qhQM7RxKtwg/dpzNqjHe65wYVnFAovLMx9vvcQpy1gBDEIo19Lnza+6f+o96yXUhs4icIiOjekZc15V60vL1/HYuyyVXv0zz4uWp5LdNa8ksNLDzXBbRHbqV+9w5LCWEQJIkgiNbk5ueXLbFHjr3m0nCqY/Iz+7DgjdKeObdJLz9XEtwvJJbwo9HUnmgd6StktENxrEr+ey7mIMk1T5QsT3XfYDNwEAgDUPpSGxLg3BpGef2Zf/l8qnDnN70Lc+N+qLRvkdTU+8hmlarfVWr1T6h1WqnNaZA0z5djk9AMCpPW0BcKGwZtPYkKfvsbsZXqxj36JMMGnALG5cv4uF7buerL78ot6i5JRPhr+aR/tEuDyAqxr0tJiNePjnASCAbyTqa5Pjp+AbWHtetbg1cbomRFbHJHLuS75KitSSMZiu7zmez5kjqDWlwr5U+NwXhfmom3NIKbbugSnFW+/Pirx9/z6Axj2IyGhg05lFe+WoNg8Y8itrrAv/4KovAcCOJZ7yZ/3p7CnJdz9rPKTaw6nAKmYUNKw3YkjBbrOw4m8Xe+GyXnwMvfLYTjc8RbAY3ARiM3eACmI0GJAmO791S6bkz84F+ZfUJViBJEt8sXIhGoyEwsGUmtNXL6Gq12sFASGxs7PdAkFarHVhfAdLS0vj8n39xXOiDm1dRnJ/riN06J0m9NqoH52L3suSb+bz5+L2s+PZrfvpxdX1P7faolAqGdglldM9I1KraHwQViwmUFBUwaExvHnstDoVST3bKnaxfEEFteuLs2q+IxWpzN/9yIv26SSy6mFXMD4euEJeS7/K6wpqob1ON5qIx9bm5UCgEgzoE86d+0fhrruZv2BuVRLbvwvhpb/H2D7sqNS4Ja23kyVlH8FAnkH5Zw/zX2pOX4XoOSLHRVjbyUvb1v4ysoNTEmqOpnE5zvfF8XqaK72f3R1/cHjiDQnU3cAlF2YTKXhCp//D7KS3Mr/TcmffLPh6e8AheXraETi8vLx599FHOnj3bSN+qaamvT2Q0cKbs79Nlrw9Wt3FmZma1B3rrrbe4dOqoI8OwOtRqDffeN5J33noLtamQrKzC+knuIjqd+3SG8QOGt1ez4bjJUQqyKh7+x2zH3yOf/gcjn77qSp78ZiI/zO7Mvl9C8NCUMnRCWqX9P3hscLVLMGYt31du27PFxSSk5dAtEPo34LtdC1z97UqMFmISC0nMa9wCF5u/+4LLpw6z+bsvGDv1n+TnW9Gp3Noz4LI+16TLdppTd5TAiPae7EvQk5B79Xd1LjVbFfs3fILJsAdvvxiyUzvy5fS2PPn2OUKjXZ/Brj5QRN9WPvSN9qk1s9mdni92apMpWWdg96V8DGbX6wvkpKlZ8m5H8rPVqL0v0G3gxwwa8wE/fvYW2ckJqDw8a2yl98Ovv3Nbp3D2qD3R6/Wo1Wr0ej0qlQqFQuHS/djYNPS3q6/RDQXyyv7WA5E1bVzVmr3AwMDyilBh+uWh1hAcGkFmahJqtRqj0UhURAQ9e/asp8h1pyFrDRubcOBhleBoNiTUY0Tde5AFXk9h6ZzW7FzZmoAQJXfcn1dum5qWYFRM27dzPLuYUrWZYV1C3SrWW9NvZ7VKHE/J51BCHkaLstrvBpWz6Kt7DyrnI8RuXUPs1jV4eKq5GH/Bre6nCrisz65+h+b+rhOjIjmSpGP/pVyHC7Sq37nib1ZSeAuwkYLswSx++2amfJhIdIerhre6397OeZ2ESSVxT7fQWovLNPc1qoqqZLJaJQ5ezuNwShEqtReqGpbCOl+fkoLWfPt2O4ryVLTrXsKz71nw8p0OQGTbjnTuM5DbRk9gz09LiD9+gJLCfMdzp8/ge/j8/z6mdZA34eHhFBYWMnXq1HINCJrz+jXk3PWN6WYB9l5ZfkCdi/aeOXOGiRMnOlwGHmoNIdFtEULg4anGbDTi5SGYOnUqe/bsYcqUKWRktKzU8MbGQ6lgTM8I+rapXyyjfY9LBEfaZsNr50Wxb1350XhN9alrcpmm6EpZ/kcyMZdyMdZhFNwcpOXrWRGbwr74HJcqglXlaq/O/T5z8dZyfZCVHj6ovSfTtVcSq1e71lqumWiwPrsjt7QNZFyfKLxqMH4Vc0g81EZ6D/mUDr1yKdKp+O8/25frWW1vJfjZCxOqDR8kZBez6nAK2UUtP86rKzHx45FUYhPzXAq92HVj7fxfmf+6zeB26lPMlA8T8fK9qm/O/ckfnT6b7rcOLffc6dkunFu6tndsv3LlSubOnUvv3r2ZO3dui87dqe9MdxMwClgF3Az8WtcDREVF4e/vj8FgKOsMYkAhWZn81DO8+NxfHaMZe4eHxu700FIRQnBnpxACvTzYfT67TjHI7cvmk5u2Ct9ABUW6mfzy3y4EhafQ47ardWirq09dW51rqyQRm5jH6bRCBrQPpGeUf7MXIHGmoNRETEIuFzKKXbpmtZUedX7PeRlW/PGDmAztEIopWEyTsZgiOXkYVigMPP98436nRqTB+uyutAnyYqK2Ncv2X6Cq9Dh7DglczaD18fPgsVcz+OFfKk7u92fBG+0wm0ZjtWxx7FeYm8X7k4dVuwRPV2pi1eEUbu8QQp/W/i2ykMap1AL2xue41iGonL7cQdy+GYAKITbxzHs34eHp2vLHhyc9yZlda1vc2tu6UC+jGxsb+7tWq71Lq9U+DehiY2P31Oc49p6FbbT3cGrfZkp02Xzz368A2cjWRq9W/qhVCradycRaS2ZURQNSpHsDsIA0i8XvhqNQTuFfGz4FKtentmcO2qmt9WKJ0czu89kcv5LPrTcF0znMp1mNr8Fk4Y9EHSdS6la+sSpXe9f+dwBw7vDvVfQmhjWf76UwbzEwBsnxnDoDLOKPP74nMLDALWN5jaXP7oqfRsWY7kEczpQchU6qKpxhW1qkoDAvB5WnxONvJLPq02iO7AhEqdoEYjxIv5Tfx2Rk5gP9qtQFe9JhYm4JI7qFtZi6AfmlJnadr1tRGLu+nPhdwmJaBfig9FjL859ItRpcsD13ercOYEinEMSf7m6A9O5Pve+C2NjYDxp6cruLIDMzk/Anxjb0cDccXSJ88VAKNp/KqNGg2BWifMnItxCKECTr31GqNnH5dBLBkUmV4lXVxXmH/ukZ5r32FONfeq/KWJmu1MTW0xnEaDzo1yaAm6P88FA2XRGBEqOF48n5xKUUuLxw35mqXO1+QaFIklTuPbWXHx8+uQir5VVgVtnepdiqHX0DHECt0TDqvvv47LPPGu8LNjKNoc/ujKdSwf29wth9IZuTqQU15i/Y732lEib+IxW1l5WYDcEg1gBPYvttQaFQ0mfofbU2E0nKLWHZH8kM7hhC9yi/a/xN649VkjicpONQQh7mGpJaq8I/OIzigruwmKYBauBbLKa/8MfWCbTpUtkz5hz7DQgO545OwfSrZ9ispXHjllK5Trgp1If7e0fVaNAqlowEykpHPo/KcxUmg5J5r4Wx+rN1lWKV1cV5D25exeVTh9m9elGN8hXqTey5kM3imCT2XMi+5usZdSUmYi4X8F1MErGJefUyuHaq6udqf+/5T5bTsfcXHPnt31gtS4A+QDrwFirPLoREv4cQB1F5qjEaDPj6+hIZWWO+ocw1RqEQ3NU1jNs7hhAQHF5jCUl7DkORLouHnkvnxRYKVgAAIABJREFU7onZICmB74FptpKrVovLzUT0Jgvbz2ay5qh7rgNPzCnhl1O57L+YU2eDC/DHtgDOH3kZm8GdCzwLWB09cGfc37fc9vZw1Y7l/2Vkj/AbxuCCG1akkqk7bYK8eKB3FOtOpFUbf3EuGVmky8E3MISivBwykiYBEpJ1Imf/mAX8VsmF7Bzn/eyFCeVim/YM3drKS+pNtpnn8eR8QnzUdI30pV2wV6N0BSkxWriQWcT5jCLSC/QUF5fUmJHsKlW1grRaIW6fP8v+FUZWik12tVcGhtI3ge9ReQosJiNWS7Tjmp3dtZbs7JaxZvdGoH/bQLw9lCyuob92xRyGUX/OxMvXwsZFEcAXDLzvOeA9CvOya81odia1LOmwna/E8MAQvDybt31mRoGBmEs5XMkrpbjEhE89ViDsXRvMuq9tA8oh4y9TkLONUwfUmAz6Sh3gKrr1929YQa8NK9BoNG4ZerkWyEb3OiE6UMOYXpGsP5FWpavZ2YDMfKAfGYnxTp8+DngA44FtwF30u6udw23mvO+s73+rUG7yamNpZ2p6EOUUG9h/0cD+i+DtqaJNkBfRgRqCvD0I8vbEu4YHkSRJFBsspBXoScvXk55vILPI0CQVsuKPebPxfxEkX7Bns14C3sdQuhSwFQoxG0EIBa06dncY6j6dXmT+29NIT0+XZ7tuQvcoP1avWsmvpzIxW62O36qmMrRtu/Xh/ilL2bCoCwc2dWfQ2K944s101s57r8Ykw4pYJYmT6cWklCTRu3UA/doEoGni3tVp+XqOXsnnUlblxEJXBxGSBL9+F85vK22t+R6Yms6dD5Ww5gsfR63rih3glCoP+g0b43h+eHl5MW7cOObMmXONvqn7IRvd64g2QV6M6RnJhrj0GpOrKsd4zcCj2IrAjwV+w2KqWuGqcjfHHz9Uabvasp3tlBjNnMso5FzG1WInGg8l3h5KVEqBUiFQKQR6k5USo4USk6VJDKzzg6e0sBUbvongbKwtHucfbOKeyVl01Saz+dssTsaoMBnMVcYFAVZ+M5dDhw4xe/ZsPv/882suu4xr3BTqw4N9o1h/It0RhqgY61V5qlF7+dCx9wDi9m0lst07PPnmx/wwpxUxG4KJ2bAdWAtItSYZVsRosfVoPpGcz83R/vSI8ruma92tVomL2cUcu5JfYwu+2nS3IDeL72f/k8DQnzm2OxSFQmLslHPE/f4EfYZ+QpEul/7Dx1GUn8uFI/uxWi2O6zh19kJif12N2WREo9FgMBjw9/e/oQajstG9zmgX4s2onhFsOplRrXGqqi0gmICH8QvaQ2HerZyMmcWVc1m06VpZOZ3dzUvnTCfrSoJDQV1tLF4TepMFvan+sdjGwLYeM4GFb5SSeaUjVqvg/7d35/FRVefjxz939iyTfScsAQRkD1wFRQQFWxFFpdqqoPZXS1/+LNZuLrgULdSWaqsWq62KSq2AiAqoWECwLArKhRIBQUWQnSRkX2eSzHz/mEyYTGYmk+0mkuf9evEymbkz82S85z73nnvOc6wRdVx09VEO77uNwWPnh5zXDE2vml544QVeeOGFbtWV1tWlx9qYnp3OqpzTVDprA/4/rXU6+HyLZ7qQd382GCdjjfgAR9UPUZQM3O5pmK1VIVfJCcZZ52L3sWJ2HysmLcbGkAw7WYlR7dL17HK5OV5cxdd5FRw6UxGyXYWqSOfbdte+tohv9z0EpGO2urj1wePs/+zRhkTt7Rl7a+FjuN2uRt/jzrUriHZX8LNZsxoVuuhOJOmeg/omRTF5UDIf7s8POic10D3elMwsSgoeRVGWsW9bDP+cE8kd846SNaSq0Wtvf+QZ5kzLZtv7yxoeOzuP1TM9yGAw4nLVNbtcV1fjSZR1wJ3AV5w+kgDUoRgW8cDLE1j377kc3f9xw0lGsHnNcPaq6YvtG3BUd8+utO+CpGgrP8jOYGXOKcqqa5pduzv7sqlc/dN7qSg5wrO/jsNZfQnwCTWOKWEPrArmdGk1p0urUThDUrSFngkRZMZFEB9pxm4zNTvf11nrIr/cwakSB7ml1ZwsqQ77BPae51ay8fW/BxzRDd62EQ+swrNwQQE1jqm8PPdsxVDfRD3ogkubfI+bVy8FwGaz8cwzz3TLqaGSdM9Rg9LsVDrr+PibwMWFfO/T+qurPc7SJ3qQszmWlx7uze2PHGPAqMalJwNPQwLveqSu+ns5NY7qNh+I9HTL/Z+y/KlYqiuyAFCUjQxU3+Lg7pd47ObQVwH+C597r5qcDgdWq7VbdqV9V8RFmrkhO4NVOacCrt0NnhH/uN0N+3NMgoOsIbM59tUCKssGYbLsYtd/b2DMlAOs+scfwxpYFez+qRs3+eUO8ssd7Drq6RUxGhRibWaibCYMChgVBUVRcNa5qHDUUuGoa9NofXt8UsiemzvmbeXlub2pcaQAhzGZr2fQBUnApIBz172V7N578Qn2bduAs5vew/UnU4bOYaN6xbVqKL7RBLfcd4LRk4pxVhtY9Lte7NzQeIlB3y5qbwm9pIxeDSUQFYORgReMZ/Tkaykr6vpVBUvOmHj9Tz341/yR9Qn3MAbTjbjdk4lPKWhS4tG7MsqcV9eFfN/y4kKuvGEmq1atklKmXVy0zcT07AySo61+a/F6DpPDxk1umDrm9dP5j/DAK5X0H1lOrTMeR8X7vDz346CrdPkLtaKXvzqXm8JKJ8cKKzlSUMmhMxV8k1/OscJKCiucbUq4XoGmyQF8uTOKxb8fVZ9wt2M0T6C2JocjBz7HGhE8UcckJBMTE9Ot7+H6kyvdc9y4fglU1dRx4HTLVmUyGGHKj3M4mHOUkjO3suzJHpScMXHZDwvw9nCVFxcy+nvTGT/tFraveZMD2pZG6/kmpGSENZqzM9U6FbasTODDpck4qw2YzHUoygKGjtvNxBtuZvsaU0OX8cGcT4MeXIK5/ZFnGJhqZ3ASTJw4UYe/SLRFhMXI9SPTWf356YC3Dvx7MwB+f/MIamvcwN+AOykt+AuQyrb35zQa+ex7NTvv5nHU1dQ0vEdrxj50BP9pcm43bHo7gTWLUnG5FGISNzHogkWMu+Zpliy4n9yjBzm0d2fQWyzxkRaiXRXM6sb3cP1J0j3HKYrCpIHJVDjrONaCsm4AG5Y9T2nBcnoOqObYV3fwwaup5B2ro+D0dG59cAG3P/IMFRUVREVFMfmWO8nZ/B9GTZrGpdff1qTxtbeWzI0M5oAWxep/pDXMt42M2UjfoUvZt20RtsgfNqy5CvD2s545mam9+3HLfX/u8L9PdB6r2ci1I9Ix//UFjhV5xjMESrZeZ2+1/JJaZw6wELgPRRnO0HGLsVgr2bXx3UajgYdcfAWfb1rTqrEP7bHvh8NRpfDm0xnkbPb0cl1y7RGOH7yXXRty+Ow/rzVsV5R7gm3vL2PHurcbnTDER1q4fmQ6M1csb3isO97D9SdJtxswGBSuGpLKil0nKahoviKU/6jbY1/9DE8N/NfZuSEDWMCal5dw02/vadjmwyXPU1VegsVqa5SsOkq4U5Kg6UEq/7iFd19MZf9nnilAZuthapx3Ulm6jr2feF4TaIEDgNwj3/DUz3/Q6VckomNZTAauHpbGB/vy+LYg9FKajWcDvIDbdQBYgdt9JXu2DsYzHc8dcJ9qzdiHYPt+W5NxWdEZFj96FzPnPImjsgeL52eSe8SGNaKOH/3mJF//736OfKEx6vJrcNXVNZlW9bPHX2x4L2/C/a7Um9aTfCPdhMVkYNrwNN7cdYJyR23Ibb1n7v/77/s+j74NXAasACawc0N/dm64EdjW6LVt6SYL56DRmilJ3oPUfxa/SqT9CbauSqSuVsFiq8VZ/QA1jr/hmTLVWPZlU5nwg5+wacXLAUd06nXFITqHyWjgqqGprN+fx9d55SG3bTwb4DjWyDsoOLGAitKBwGbgIUyWhQxSLwbggLbVc7/YYGTA6IuJjk2grKgg5D7V3L7v3c/XvPxXCnNPtni/3PTmIg7v3cmSBfs5/vUlOKqMpPR0UHDqAv41f0/Ddjs3rD77HflMB9q+ZjnTZ/9OEm4z5FvpRqJtJq4ZnsZbu06GXEvWe+YOnupK7volcxTDZ7jdF4B7GXApirKJsdfkUFXyGPu2fxhwmkFLhHP1GqpQfZNtGw5SZuAudqybi2e9dheK8irO6geAvCav8x2l2qPfoKAjOt9+tmWViMR3j9Gg8P3BKZiNBr44VRp0u0CzAYrycnniZ+upccwGFlDrnIzZuhprRF7DAET/sQ/++5RvEp791FJefGgWjqoKap2Ohn1/z9b1jVYC8ybF+TMv589r9jSJy9/ZdpIIrOCbz6cDoChvcvfTw3BWL2zS5iLtsZQW5jeaueA9CbBarcwsKQnj2+2eJOl2M0nRVqYMTWX156dDVnYqLy7koqk3UV5SyJ6t6zzJ1+UCTmE0X0VdzXzc7l+ybbWKPeFP1DimYbKcCHuAka+WXL02V5DC1wOvrOPfj3/Ct/tvBHd/AAzG7cAvcdV92mR7r2HjJhMVk9Bwz9Z/QM32NcsbdRN2lUEwomMoisLlA5MwGxVyjoefTD5a/hw1jjeIS95NdeXfqa64gpxNl5Da+yVGXeHi0mtvbhgbEKwNeEZOuxtGN/uv/WuLjA7SMwVut4t7pwxpdr984JV1vP7HLRzedweQDpTQ+/yXuO6uLF6eeysz5zzZpM0NHjORybf8/0bJ2GK1MW3atTz5xIKwv6PuSJJuN9QrIZLLBiSx8cvgRfi9Z+6L593DRVNvYuxVN/Lq73+BAtz+u7+xfc2bnDj4KAWnH6KscAgG4z7GX3eAqvI/U1bUsuL+/levAIkZvbjriX81bON7xh+qIAXUL0rwsZ0Pl2Rx8tCE+ke/BO7HVbeKpB69OXOiaRznXziBuOT0JqNU/Ud0Tr7lzrCvtuMjLWTG24DgZfdE16coCpeel4TFZGDHt0Uht/VPoMX5i4DVKMrfcblu5NThuzGYZqAoRUyfPQgg4LxgoKGXyf9esO/av8F6pkLtl972dNVPnmXD0lEc3lffTpQt4L6VjL5j+ew/OxquugO1Od8TYLPFSm2Nk4T42G49HSgcknS7qSEZMZRU1bDzaOhyhL4J50GfOanepJR3ai/rXu1LzuZYPlo+kszzFjH1J7lAZdj3PGMSktm9+YP6K2mPgpNHmTdjYsN0i4TUjCZl5nzjAHDVwd5P7Kx7vQ+5RyIBMJkLqK19GNwvAp5BK2dOHGkSQ2rvfhhN5rAGgDV3tZ1qt3FeahRZiVHERZo931OeJN1zwdisBGwmI1sPFlBSmBdw/w58C+RCrv5pCm/89S98tXMGJ75O46nZ8aiTi/n+rfnEJjXdp5IyelFSkFe/Wo9nrrDb5QpY4ztQz1SoXqC1/3qFw3uv4bnfZuN2WTAYK+hx3htM/3kcf7vnGNveP9tGvAnfZLYwffYjjdpIeXEhE6bdwqP3zmbpa692++lA4ZCk241d1DeBkupaDjYzSCSUqJhaZs45wfBLSln1jzSOfx3BP+f0YaBajjXi1bAHdgwYNY6Ck0cozj9NbX1N6JETprB70wcc3qtxeK9nu0BduRWlRj5bG8e29+IpyvMUjDeacrliRimXTq+lqvwm3nvxWJPqWYrBwIDR44iOTcBRWRGySpc//zP/ipIzjMiMZXC6vV2WKxRd18iesVhNBu6aHfiefqCTst2bPuB/H3m7f/8AzMXtuosd6+LZvSmW8dcVUpRHo33Kd967d78NdkslUM9UoF6gB66ZSF3tncBfgQQ8F8WLgYe4Y/47REVFNVlJLNQV86/++DzX1Q+aGqtmt9t3fC6TpNuNKYrCFYOSKa+uDbnqSDiGjy9j0AXlbFmZyH8W2/hSiwH+DFzJzg3PA7uZN+MysoaODph8fzrvH7y18DE+/eDNhgPL2YNUY9mXTWXKj+/jwI5odm+KIWdLDLVOz5VAYrqTqNjFHD3wC0rOXIvZ8jvMARZ48A6Wam0BD+9BLi7CzIwp4xmUGo3JKAXeuoO4uDiqq8+2l0Angv4nZXnHDnP6yNf1g6CKMFnu57zsfbhdf+DAjmQ2vpGE0bSMEZeWUFdbyPTZg1g87x4GqeMD3toJNkc8WC9Q7lEL2vo4TOaT1NV6D/tbQHkY3JvJnjitYdtwx00kRlm5bmR6yKU4RVOSdLs5k9EzH3HFrhMUVzWdNtMSFpubSTedYfDYYl6bf4b8E5OAy+v/nQKWcHjvWubNmELW0CFNkq/vgWrz2//iYM52KstKzt7jUlLBPY4TB+/i6dkXU1l2dvcdMLqcg7tnUHDqXQpOeQaI+RdfD7TAQ2sLXKTF2BjVK46+SZHNFqEX55b9+/fzwAMPsHr1aqqqqgJeCfonv7ef/T3ffO4ZvOcdtRyXVMr02fl8u7+cTSsS2bfdzq6NcezaGEdG3yqGXLSEIWPLSM+qDnhrJxS3G4rzzOzcCB+9WYOzqn/DczGJeygtmA1s9pZKb7Te7Z/e3d3suImkaCvXjUhvl5WQuptWJV1VVSOAXwEuTdO6b+Xqc0SExcg1w9NZsesEVe2wpF56nzj6jXiG/BO3AbfhWbFnMPCb+n/VHN67hXkzdnLdXTeTmO4kNrGWK2+rrz+rwJgpT1Fy5j0O5uQC/YGx4PYMOsk75tkstVc1Iy4tZeTEUpJ7OCkt/DXvvVjX0I0cbH3btki12xiTFU/vxMh2eb/OJm255dLT04mJicHhcHjqCTud2O0xAfcx/0FV0HgQFECf86vo88hxCnPNfLw6gc/WxnHyUAQnD0Ww/vVkYpNq6DmwivQ+DtL6VJOU4cRic2GxuTFbXDiqDJQVmigpNFGcZ+HI/ggO74uk5Iy54TMVpQy3ezkD1QMc+/Ilho8fg6NqfMN6t4rBiNtVx8gJU4DgV8zgOeGcNjwNq1kSbmu0KulqmlalqqoGXNzO8YhOEhdp5uphabyz+xS1ruBzeMPlGdgxhfKSL9mzdQgwDpgKfA8YDVwBXMHK50K9y92NflMM1fQbVkffYRUMG1dGWp/G1bX8F2FozfSlYJKirYzNiicrKarN79WVSFtunby8vEb1hI+fOEVClIXCisYJNti88stv+Tlpmb0btistzGfZk55BWVfensI3OVHs2x7NF9vtlJwxU3LGzN6PWxplIZ7CHEtxu1cD1XypeZ7Zs3U9Y6bc0FARy13/X+8Vr29Xue+AyCH9ezN1aCpmuZXSam3pXnY2v4lHXl7TAgS+uuKC3t0xJgOgphnZeLA85BxeX773tnzd8OvHAVj25/tQv/8DKkuL+GLbg8CDeApUXIrBeD6xyeOIiM4m/2gl9sQUDAYjbjdYI+uIS3YSl+IgLtlBRt9K0vtWYjSdjauiwlO6bsVTD3HDr/6APT6J4jN5jLz8WsZMuQFt/TsU5edSURG6jF8odquJUZlR9E0wo7gqyMtr3Xt1xf3JR7u1Zeiaf2t7x7Rw4cKGnx966CHAsxj9RwcrOVFy9mTQaI3EUH8CaDJbqHU6MJptmCOiG+2XHyxeyLf7dvLB4oVc/bP76Tm4nJ6Dc/nejyHvaAS5RyPJOxpB3tEIivMt1DgMVBRXUeM0YrbUkZRpITquBnuCk4y+lSRmHENb/zgHPttIXU3T/71ut4vta5YDCv2zx/JNzme4XXWYLFbOH3MZ37vtFw3xeWPbuuw5frLwCYoK9Ks5fi7uS80mXVVVHwQG+D28Egj7k1NSUtplG711x5hSUiDSXhpyDq+/qKjgV393PPZ34OyoyrNTGlbidr3DoNE/BBZz6pvlDBz1w2YGNTXt0l37yl84un83n6xczPTZv+OOx/7esAhDcnom//7jb6lzVLb4ajfCbOTCPvEMyYjBaGife7advT/p1ZZbsp2e9IhpRmoqWw4W8PmJs0U0HOWlTe6P2mw2oqKimnQ/a+veQlv3VqMrTfsQ6DekGs9c76Imr6lxwqlD+BXBSOTLz2Jw1dY0DB705XvrZf3rz/HN7u2YzBbqapxEx8SSltm7yed89O5yst5djs1m0zUZnmv7UrNJV9O0xwM9rqrqxFZ/qujShmTEUFXjYtuh9lsHN9CUhqfvvrHVlZ1CVbF6eOlWoGWLIniZDAZG9oxldK84LKZzqwtN2nLHMxgUJgxIIj7SzOaDBbjd7oD3R71XkeGUNfWf7x5uKdTG9aALqCwvpawgr8kcXu92Iy67mpyP3msYNOX9nC+2b8RRXSUL0LcTGb0sAlJ7x+GorWNXM8UzWsr3ANSS+YD+Qh145t98SYsXRVBQOD/dzpiseKKlULtoo+GZscRHWVi7Lzfk4MRg03MAnrv3dmbOebLJyWM4U3pKC/OpKC3m+p8/3PD44nn3YI9PajIi2dsmKyoq6OczaCo+KYXzMpPJcTpkAfp21KpTeVVVTXgGXgxRVTW+fUMSXcW4fokMTo/p0M8ItjB8aWE+z917O6WFgbu5/Q88NY5qvvrfNhbP+wV3PP4y2ROnYrbaAE9XWvZlU5njM+3CV+/ESG6+IJNJg5K7XcKVttxxesZHcJOaSVqMLeR23ivNu59awtirfkRZUQEfLnmew3s15s2YyLb338Dt9iwNeO+UIcyZlt3oNaMun0bOlrWN2opvova6/ZFnmD77kYalN0MVg4m0mLh+ZAaOsiJmzZrF5s2bmTVrFrm5uW3/Yrq51o5ergUCdlWJc8vlA5Nw42b/qbJ2f+8PlzwfdGH4cNYM9Z1LuGTB/eQePUhFcSE7178T1uT+5Ggr4/ol0DPh3Jj+0xrSljtWtM3E9OwMthwsYM+JwIsl+Ca/HevebjLFyCvYFDiLzUZVWQkfLnmeHeveaXEvj7+MuAiuHJxClNXEG2+cvf0jC9C3j+51Wi9aTFEUJg1MRkEJubRZS/jfj/VdGB5otExZsDVDvTWY50zLZtv7yxq9v7burfrYDdz91JImk/vtNjNjs+IZmBothS1EhzMaFCYOSKJXQgQbD+SH7G72v23inT/rHfnse/IYaFwDeNqst/enpUttZveM4+K+CRjaafCgaOrcGikiOoR3abP26mqe8+q6oN2/wZ4DTzL272pzu90MvWhSQ0F48NRUHnrxZB7+98ZGXWlWk5Fx/RKZeWEmg9LsknCFrvomRXHLhT1DzvX2v23idtWR2rsfdz+9tKHr2StYWxl1+TVhLX3pK8JsZNJ5cVzSP1ESbgeTK10RltauKRpIcwNBAj0XauDU+tefazQlwu1yYY9PbHg/k8HAiMwYRveKkyo6olNFWoxcPSyNeIOD/UXugFe9gUowek8efQVrR2VFBSFLOPo7LyWaCeclUVbcfrMVRHCSdEXYvGuKxtjMbD1YgJvwCmgEEqq2a3Nrd/on6vLiQuJTe9BzwFAAjn65h7KiAhRFYXC6nQt7xxNtk11ddB3nJUcwekAinx4uYs/J0kbFaEKVYPQXqK2E+/pIi4mJA5Lol+y58m7/URsiEDkSiRYb2TMWu83Eui+ar04UTKgDQ7DngiVq/1GYlRWVjMhKYUxWPPGRllbHKERHspmNTBiQxOB0Ox8fKuRYYWWL36MlCdrLYjSQ3SuOkZmx59xc9O8CSbqiVfolRzE9O503P61sw/Vuy4RzgMlKiqJfHxvnZ6XqFJUQbZNs96zYk1tajXakmMNnKtvUixSM0aAwNCMGtXe8LMfXiSTpilZLjbFx7ZBEvihW+Cq3vNPiUFDISorkgj7xpNitYdUHFqKrSY2xMXVYGoUVTvadKuNgXjnljto2v29ilJUhGXYGpkZjkzENnU6SrmgTq8nA9wen0Dshkk1fncFZ1/YVisKlKAr9k6MY3SuOZLtVt88VoiMlRFkY3z+RS/olcKK4moP5FZwuqeZMhTOshUiMBoW0GBs94mz0SYwktZniHEJfknRFuxiUZqdHXATbDxfy5enyDuke8zIbDQxOtzMyM5aYCHPzLxDiO0hRFDLjI8iMjwCgts7FmXInhZVOnLVuHLV1OOvcmAwKURYjkRYj0VYTSdEWTLL0XpclSVe0G7vNxBXnpzAyM5ZPDhVytBUDQ0JJtds4P93OgJQomfojuh2T0UBarI20WLly/S6TpCvaXbLdyrX1A0MOnC7n67zykFV4QkmMstI7MYJBqXYSo2UkshDiu02SrugwqTE2UmNsjO+fyJHCSk4UV1NQ4aSg3EmFs+kAkQizkbhIM/GRFtJirPROiJT5tUKIc4oc0USHMxgUspKiGpW/c9TUUevy3Pd1A2aDIl3GQohzniRd0SmsZiMy3lgI0d3IEDchhBBCJ5J0hRBCCJ1I0hVCCCF0IklXCCGE0IkkXSGEEEInLR69rKrqJOBRoAfwc03TPmjvoIQQ+pD2LIS+WnOlG6Np2nhgFvBkO8cjhNCXtGchdNTipKtp2jv1P+4ATrVvOEIIPUl7FkJfIbuXVVV9EBjg9/BKTdNWAlcBfwrnQ5pb37S4uDict9GVxBQeiSk8XSGm9mjP4axV3BX+Vn9dLaauFg9ITOFqa0whk66maY8HelxV1SQgStO0ZeF8SEpKSrtsozeJKTwSU3g6O6b2aM/h/g2d/bcG0tVi6mrxgMQUrrbE1OLuZVVVo4CrNE1bpKqqSVXVxFZ/uhCiU0l7FkJfLRq9rKqqFXgfsKuq+gsgFhjVEYEJITqWtGch9NeipKtpmgOY2DGhCCH0JO1ZCP1JcQwhhBBCJ5J0hRBCCJ1I0hVCCCF0IklXCCGE0IkkXSGEEEInknSFEEIInUjSFUIIIXQiSVcIIYTQiSRdIYQQQieSdIUQQgidSNIVQgghdCJJVwghhNCJJF0hhBBCJ5J0hRBCCJ1I0hVCCCF0IklXCCGE0IkkXSGEEEInknSFEEIInUjSFUIIIXRias2LVFX9PjAbSAOu1jQtt12jEkLoQtqyEPpq7ZXuUU3TrgHeAca0YzxCCH1JWxZCR61Kupqm7a//sQz4sP3CEUIELiUlAAAEBklEQVToSdqyEPpqtntZVdUHgQF+D6+sf+2DwLH634OaO3dua+MTQrQTactCdD7F7Xa3+sWqql4IzNU0bWr7hSSE0Ju0ZSH00dbRy4eAfe0RiBCiU0lbFkIHLR69rKqqAqwBNgAlwLz2DkoI0fGkLQuhvzZ1LwshhBAifFIcQwghhNCJJF0hhBBCJ62qSNUWqqr+BsgDYjVNe9bn8QHAj4BK4F1N077qAjHdDPwSiAFu1TRN6+yYfJ5fBLymadp/u0JMqqoOAsYDezVN29bZMamqej2QWP9rpaZpS3SM6VI8I4En+T1+MTAOz8nuK5qm5ekVU0eR9ty2mHye17U9S1sOO6Z2b8u6XumqqnoJkKhp2mtAvKqqvhVwngGeAp4F/tTZMdUPMqnUNG0M8CTwWGfH5PP8NUC0XvE0F5OqqgOBWZqmvahzIw31Pd2jadpLmqa9BPxEr5gANE3bDEQEeOqPePalpei4P3UUac9ti8nneV3bs7Tl8HVEW9a7e/kqwFsB54v631FVNQLop2lauaZpDiBLVVW9rsIDxqRpmlvTtFX1j+8ATukUT9CYAFRVzcLTQ7E/wOs6JSbgb8ARVVWfqW88XSGmnaqq/l5VVRV4TseYvJy+v9Rf+dXW71dH8VxJfNdJe25DTNBp7Vnacsu0a1vWO+kmAUX1P1fjKbIOEA+U+mxXCyR3cky+JgN/1SkeCBJT/YFriqZp7+gYS3MxRQF98FzR/AV4U1VVS2fGVO8RoB/wBLBZp3hC8Y0VPPv8d5205/B0tfYsbblt2tSW9U66+UBk/c92oKD+5wLA5rNdJFDcyTEBoKpqf+CIpmlf6BRPqJguBWaqqvpf4MfA06qq9ujkmCxAlaZprvqzvpMEPtDpGRPAH4A78XQBLdMpnlB8YwVwdFYg7Ujac9ti6qz2LG25bdrUlvVOumuA4fU/DwbWqqoaW98FdURV1UhVVW3AMU3TqjozJgBVVVOBEZqmvaWqanT9mWCnxaRp2kZN0y7WNG0i8CrwS03TTnRyTEWAQ1VV7z2pfKBTY6r/fbimaWWapr0PmHWKpwlVVY2qqto1Tfua+kSkqmpf4L+dFVM7kvbchpg6sT1LW26F9mrLuiZdTdM+BqpVVf1/eM58i4F/1D99P3Af8Cvg150dk6qqicBaYI6qqhqwCc9IzE6LSY/PbmVMs4G59aNDF2iaVtcFYnpKVdW7VVWdDvxTj3i8VFUdBvRTVXUonntTD9c/NV9V1fuAmcBDesbUEaQ9ty0mPT67FfFIW/bREW1ZKlIJIYQQOpHiGEIIIYROJOkKIYQQOpGkK4QQQuhEkq4QQgihE0m6QgghhE4k6QohhBA6kaQrhBBC6ESSrhBCCKGT/wMyMjWWYFvc8gAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 576x216 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Set into eval mode\n",
    "model.eval()\n",
    "likelihood.eval()\n",
    "\n",
    "# Initialize plots\n",
    "f, (y1_ax, y2_ax) = plt.subplots(1, 2, figsize=(8, 3))\n",
    "\n",
    "# Make predictions\n",
    "with torch.no_grad(), gpytorch.settings.fast_pred_var():\n",
    "    test_x = torch.linspace(0, 1, 51)\n",
    "    predictions = likelihood(model(test_x))\n",
    "    mean = predictions.mean\n",
    "    lower, upper = predictions.confidence_region()\n",
    "    \n",
    "# This contains predictions for both tasks, flattened out\n",
    "# The first half of the predictions is for the first task\n",
    "# The second half is for the second task\n",
    "\n",
    "# Plot training data as black stars\n",
    "y1_ax.plot(train_x.detach().numpy(), train_y[:, 0].detach().numpy(), 'k*')\n",
    "# Predictive mean as blue line\n",
    "y1_ax.plot(test_x.numpy(), mean[:, 0].numpy(), 'b')\n",
    "# Shade in confidence \n",
    "y1_ax.fill_between(test_x.numpy(), lower[:, 0].numpy(), upper[:, 0].numpy(), alpha=0.5)\n",
    "y1_ax.set_ylim([-3, 3])\n",
    "y1_ax.legend(['Observed Data', 'Mean', 'Confidence'])\n",
    "y1_ax.set_title('Observed Values (Likelihood)')\n",
    "\n",
    "# Plot training data as black stars\n",
    "y2_ax.plot(train_x.detach().numpy(), train_y[:, 1].detach().numpy(), 'k*')\n",
    "# Predictive mean as blue line\n",
    "y2_ax.plot(test_x.numpy(), mean[:, 1].numpy(), 'b')\n",
    "# Shade in confidence \n",
    "y2_ax.fill_between(test_x.numpy(), lower[:, 1].numpy(), upper[:, 1].numpy(), alpha=0.5)\n",
    "y2_ax.set_ylim([-3, 3])\n",
    "y2_ax.legend(['Observed Data', 'Mean', 'Confidence'])\n",
    "y2_ax.set_title('Observed Values (Likelihood)')\n",
    "\n",
    "None"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
